<!doctype html>
<html lang="en">

<head>
	<title>A*寻路算法(threeJS)</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<link rel=stylesheet href="css/base.css" />
	<style>
		#inset {
			width: 200px;
			height: 200px;
			background-color: #fff;
			/* or transparent; */
			border: 1px solid black;
			/* or none; */
			margin: 20px;
			padding: 0px;
			position: absolute;
			right: 0px;
			top: 0px;
			z-index: 100;
		}

		#csvFileInput {
			position: absolute;
			left: 0px;
			opacity: 0;
			top: 0px;
			z-index: 100;
		}
	</style>

</head>

<body>

	<script src="./three.module.js"></script>
	<script src="js/Detector.js"></script>
	<script src="./stats.module.js"></script>
	<script src=".//OrbitControls.js"></script>
	<script src="js/THREEx.KeyboardState.js"></script>
	<script src="js/THREEx.FullScreen.js"></script>
	<script src="js/THREEx.WindowResize.js"></script>
	<script type="text/javascript" src="js/astar.js"></script>
	<script src="js/jquery-1.9.1.js"></script>
	<script src="js/jquery-ui.js"></script>
	<script type="text/javascript" src="js/CanvasRenderer.js"></script>
	<script type="text/javascript" src="js/Projector.js"></script>
	<script src="js/Mapbox3DTiles.js"></script>

	<link rel=stylesheet href="css/jquery-ui.css" />

	<div><button type="button" name="seach" onclick="FuncCSVInport()">CSV Import</button>
		<input type="file" id="csvFileInput" onchange="readCSVFile(this)" />
	</div>
	<div id="ThreeJS" style="position: absolute; left:0x; top:0px"></div>
	<div id="inset"></div>



	<script>
		var csv;
		function csvToObject(csvString) {
			graph = JSON.parse(csvString);
			console.log(graph)
			maps = new Graph(graph, {"diagonal": true})
			init();
			animate();

			return graph;
			
		}

		function FuncCSVInport() {
			$("#csvFileInput").val("");
			$("#csvFileInput").click();
		}

		function readCSVFile(obj) {
			var reader = new FileReader();
			reader.readAsText(obj.files[0]);
			reader.onload = function () {
				var data = csvToObject(this.result);
				console.log(data);//data为csv转换后的对象
			}
		}
	</script>
	<script>

		// MAIN

		// standard global variables
		var container, scene, camera, renderer, controls, stats, container2, scene2, camera2, renderer2;
		//var keyboard = new THREEx.KeyboardState();
		var graph = [];
		// custom global variables
		// var width = 200;
		// var height = 100;
		var length = 1000;
		var flex = 2;
		var maps;
		
		var girdCellWidth = 1;
		var halfGirdCellWidth = girdCellWidth / 2;
		var sphereRadius = 10

		// init();
		// //render();
		// animate();
		// FUNCTIONS 		
		function init() {
			scene = new THREE.Scene();

			// SCENE
			// scene = new THREE.Scene();

			// CAMERA
			var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
			var VIEW_ANGLE = 90, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
			var raycaster;
			var CANVAS_WIDTH = 200;
			var CANVAS_HEIGHT = 200;
			camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
			camera.position.set(0, 1000, 0);
			// camera.position.set(graph.length / 2, 300, graph[0].length / 2);
			camera.lookAt(0, 0, 0);
			scene.add(camera);
			// camera.lookAt(graph.length / 2, 0, graph[0].length / 2);
			// RENDERER
			if (Detector.webgl)
				renderer = new THREE.WebGLRenderer({ antialias: true });
			else
				renderer = new THREE.CanvasRenderer();
			renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
			container = document.getElementById('ThreeJS');
			container.appendChild(renderer.domElement);
			// EVENTS
			THREEx.WindowResize(renderer, camera);
			THREEx.FullScreen.bindKey({ charCode: 'm'.charCodeAt(0) });
			// CONTROLS
			controls = new THREE.OrbitControls(camera, renderer.domElement);
			// STATS
			// dom

			stats = new Stats();
			stats.domElement.style.position = 'absolute';
			stats.domElement.style.bottom = '0px';
			stats.domElement.style.zIndex = 100;
			container.appendChild(stats.domElement);
			// LIGHT
			var light = new THREE.PointLight(0x00000);
			light.position.set(-100, 200, 100);
			scene.add(light);
			var ambientLight = new THREE.AmbientLight(0x111111);
			scene.add(ambientLight);
			// initGround();
			function initGround() {
				// lines
				var Colgeometry = new THREE.Geometry();
				Colgeometry.vertices.push(new THREE.Vector3(- length / 2, 0, 0));
				Colgeometry.vertices.push(new THREE.Vector3(length / 2, 0, 0));
				var geometry = new THREE.PlaneGeometry(length, girdCellWidth);
				var material = new THREE.MeshBasicMaterial({ color: 0x808080, side: THREE.DoubleSide });
				var plane = new THREE.Mesh(geometry, material);
				plane.position.set(0, sphereRadius, graph.length * girdCellWidth / 2);
				scene.add(plane);
				var plane = new THREE.Mesh(geometry, material);
				plane.rotation.y = 90 * Math.PI / 180;
				plane.position.set(graph.length * girdCellWidth / 2, sphereRadius, 0);
				scene.add(plane);
				var plane = new THREE.Mesh(geometry, material);
				plane.position.set(0, sphereRadius, -graph.length * girdCellWidth / 2);
				scene.add(plane);
				var plane = new THREE.Mesh(geometry, material);
				plane.rotation.y = 90 * Math.PI / 180;
				plane.position.set(-graph.length * girdCellWidth / 2, sphereRadius, 0);
				scene.add(plane);

				var skyBoxGeometry = new THREE.CubeGeometry(10000, 10000, 10000);
				var skyBoxMaterial = new THREE.MeshBasicMaterial({ color: 0xFFFFFF, side: THREE.BackSide });
				var skyBox = new THREE.Mesh(skyBoxGeometry, skyBoxMaterial);
				scene.add(skyBox);

				scene.fog = new THREE.FogExp2(0xFFFFFF, 0.00025);

			}

			bridge = new Mapbox3DTiles.Layer({
				id: 'bridge',
				url: '../finalCloudout/tileset.json',
				color: 0xFF0033,
				opacity: 0.1,
				pointsize: 0.1
			});
			bridge.onAdd(null, null, camera, scene, renderer);
			ridge = new Mapbox3DTiles.Layer({
				id: 'bridge',
				url: '../finalCloudg/tileset.json',
				color: 0x009966,
				opacity: 0.1,
				pointsize: 0.1
			});
		
			ridge.onAdd(null, null, camera, scene, renderer);
			var resolution = 1;

			var reslutArray = new Array();
			raycaster = new THREE.Raycaster();
			let mouse = new THREE.Vector2();
			function pickupObjects(e) {
				//将鼠标点击位置的屏幕坐标转成threejs中的标准坐标
				var fxl = new THREE.Vector3(0, 1, 0);
				var groundplane = new THREE.Plane(fxl, 0);
				mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
				mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
				console.log(e);
				//从相机发射一条射线，经过鼠标点击位置
				raycaster.setFromCamera(mouse, camera);
				//计算射线相机到的对象，可能有多个对象，因此返回的是一个数组，按离相机远近排列
				var ray = raycaster.ray;
				let intersects = ray.intersectPlane(groundplane);
				let x = Math.round(intersects.x / resolution);
				let z = Math.round(intersects.z / resolution);
				// let z = intersects.z;
				console.log(x + " " + z + " " + intersects.x + " "+ intersects.z);
				// if (x < 0 || z < 9 || x > graph.length || z > graph[0].length) {
				// 	return;
				// }
				//   if((Math.abs(x)<=((length-20)/2)&&Math.abs(z)<=(length-20)/2)){
				//   	alert("请在边缘位置选择开始或结束点");
				//   	return;
				//   }  
				var k, m;
				k = x * resolution
				m = z * resolution
				console.log(k + ' ' + m);
				initSphere(k, m);

			}
			document.addEventListener('click', pickupObjects, false);
			var isCaculate = false;
			function cleanSphere() {
				let child = scene.children;
				for (var i = 0; i < child.length; i++) {
					if (child[i].geometry instanceof THREE.SphereGeometry) {
						scene.remove(child[i]);
						i--;
					}
				}
				isCaculate = false;
			}


			// for (var i = 0; i < graph.length; i++) {
			// 	var geometry = new THREE.CubeGeometry(resolution, resolution, resolution);
			// 	var material = new THREE.MeshBasicMaterial({ color: 0xffffff });
			// 	for (var j = 0; j < graph[i].length; j++) {
					
			// 		// if (graph[i][j] && Math.random() < 0.25) {
			// 		if (graph[i][j]) {
			// 			// console.log(i,j)
			// 			var cube = new THREE.Mesh(geometry, material);
			// 			// cube.position.set(girdCellWidth * j - graph[i].length * girdCellWidth / 2 + sphereRadius, sphereRadius / 2, girdCellWidth * i - graph.length * girdCellWidth / 2 + sphereRadius);
			// 			cube.position.set(j*resolution, resolution / 2, i * resolution);
			// 			// cube.position.set(girdCellWidth * j - length / 2 + sphereRadius, sphereRadius / 2, girdCellWidth * i - length / 2 + sphereRadius);
			// 			// console.log(cube)
			// 			scene.add(cube);
			// 		}
			// 	}
			// }

			function initSphere(x, z) {
				if (isCaculate) {
					cleanSphere();
				}
				if (reslutArray.length == 0) {
					var geometry = new THREE.SphereGeometry(resolution, 32, 32);
					var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
					var sphere = new THREE.Mesh(geometry, material);
					sphere.position.x = x;
					sphere.position.y = resolution;
					sphere.position.z = z;
					sphere.name = "sphere";
					reslutArray.push(sphere);
					scene.add(sphere);
				} else if (reslutArray[0].position.x != x && reslutArray[0].position.z != z) {
					var geometry = new THREE.SphereGeometry(resolution, 32, 32);
					var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
					var sphere = new THREE.Mesh(geometry, material);
					sphere.position.x = x;
					sphere.position.y = resolution;
					sphere.position.z = z;
					sphere.name = "sphere1";
					reslutArray.push(sphere);
					scene.add(sphere);
					caculatePath(reslutArray);
					isCaculate = true;
					reslutArray = new Array();
				}
				//console.log(reslutArray);

			}
			
			function caculatePath(resultArray) {
				//console.log(resultArray);
				var startX = resultArray[0].position.z / resolution;
				var startY = resultArray[0].position.x / resolution;
				var endX = resultArray[1].position.z / resolution;
				var endY = resultArray[1].position.x / resolution;
				startX = Math.round(startX)
				startY = Math.round(startY)
				endX = Math.round(endX)
				endY = Math.round(endY)
				// var startY = (resultArray[0].position.x - sphereRadius + graph[0].length / 2) / girdCellWidth;
				// var endX = (resultArray[1].position.z - sphereRadius + graph.length / 2) / girdCellWidth;
				// var endY = (resultArray[1].position.x - sphereRadius + graph[0].length / 2) / girdCellWidth;
				console.log(resultArray);
				console.log(startX+' '+startY+' '+endX+' '+endY);
				if (startX < 0 || startY < 0 || endX < 0 || endY < 0 || startX > graph.length || endX > graph.length || startY > graph[0].length || endY > graph[0].length) {
					alert("无可到达路径");
					cleanSphere();
					return;
				}
				var start = maps.grid[startX][startY];
				var end = maps.grid[endX][endY];
				var result = astar.search(maps, start, end);
				console.log(reslutArray + " " + start + " " + end)
				console.log(result)
				if (result.length == 0) {
					alert("无可到达路径");
					cleanSphere();
					return;
				}
				var timesRun = 0;
				var interval = setInterval(function () {
					var geometry = new THREE.SphereGeometry(resolution, 32, 32);
					var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
					var sphere = new THREE.Mesh(geometry, material);
					sphere.position.x = result[timesRun].y *resolution;
					sphere.position.y = 2*resolution;
					sphere.position.z = result[timesRun].x *resolution;
					scene.add(sphere);
					timesRun += 1;
					if (timesRun == result.length) {
						clearInterval(interval);
					}
				}, 1);

			}


		}

		function animate() {
			requestAnimationFrame(animate);
			bridge.render();
			ridge.render();
			// renderer.render()
			controls.update();
			stats.update();
		}

	</script>

</body>

</html>